package com.eigland.eigaland_lib.extensions

import movie6.posprintrecept2.module.Constant
import org.joda.time.DateTime
import org.joda.time.DateTimeFieldType
import org.joda.time.DateTimeZone
import org.joda.time.Instant
import org.joda.time.format.DateTimeFormat
import org.joda.time.format.DateTimeFormatterBuilder
import java.security.InvalidParameterException
import java.util.Locale

/**
 * Created by windsze on 5/4/2017.
 * HKMovie. GT.
 */

/**
 * Transform Instant date time to Japan's specific lblDatetime format (0-30hours per day).
 * ex.
 * 1:00 am -> 25:00 pm
 * 6:00 am -> 30:00pm
 * 6:01 am -> 6:01 am
 *
 * Cannot cast to any current existing lblDatetime format, cuz they accept 24 hours per day only.
 * Unless create a specific lblDatetime format someday.
 */

/**
 * @return HH:mm
 */
fun Instant.toScheduleJapanTimeLabel(): String {
  val instant = this
  val dt = instant.toJapanDateTime()
  val hour = dt.hourOfDay
  val min = dt.minuteOfHour

  var newHour = hour

  // if hour in 0 - 5
  // translate it to 24 - 30
  // and minus current date by 1
  if (hour in 0..5) {
    newHour = hour + 24
    dt.minus(org.joda.time.Duration.standardDays(1))
  }

  // cannot use dateTimeFormat cuz joda doesn't support time out of range(0-24)
  val hourStr = let {
    if (newHour.toString().length == 1)
      "0$newHour"
    else
      "" + newHour
  }

  val minStr = let {
    if (min.toString().length == 1)
      "0$min"
    else
      "" + min
  }

  return "$hourStr:$minStr"
}

/**
 * @return MM/dd\n木
 */
fun Instant.toScheduleJapanDateLabel(format: String = "MM/dd"): String {
  if (format.contains("H") || format.contains("m"))
    throw java.security.InvalidParameterException("toCustomJapanDateLabel() can only format year, month and day.")

  val instant = this
  val dt = instant.toJapanDateTime()
  val hour = dt.hourOfDay

  var newDt = dt

  // if hour in 0 - 5
  // translate it to 24 - 30
  // and minus current date by 1
  if (hour in 0..5) {
    newDt = dt.minusDays(1)
  }

  val df = DateTimeFormat.forPattern(format)
  val monthNDayString = df.print(newDt)
  return "$monthNDayString\n${newDt.dayOfWeek().getAsText(Locale.JAPAN)[0]}"
}

/**
 * @return yyyy.MM.dd
 * dont use it with hour and minute formatting
 */
fun Instant.toCustomJapanDateLabel(format: String = "yyyy.MM.dd"): String {
  if (format.contains("H") || format.contains("m"))
    throw java.security.InvalidParameterException("toCustomJapanDateLabel() can only format year, month and day.")

  val instant = this
  val dt = instant.toJapanDateTime()
  val hour = dt.hourOfDay

  var newDt = dt

  // if hour in 0 - 5
  // translate it to 24 - 30
  // and minus current date by 1
  if (hour in 0..5) {
    newDt = dt.minusDays(1)
  }

  val df = DateTimeFormat.forPattern(format)
  return df.print(newDt)
}

fun Instant.toPrintTime(format: String = "yyyy/MM/dd HH:mm"): String =
  toDateTime(DateTimeZone.forID("Asia/Tokyo")).toString(DateTimeFormat.forPattern(format))

fun Instant.toFullPrintTime(): String {
  val formatter = DateTimeFormatterBuilder()
    .appendYear(4, 4)
    .appendLiteral("年 ")
    .appendMonthOfYear(2)
    .appendLiteral("月 ")
    .appendDayOfMonth(2)
    .appendLiteral("日（")
    .appendLiteral(this[DateTimeFieldType.dayOfWeek()].toJpDayString()[0])
    .appendLiteral(") ")
    .appendHourOfDay(2)
    .appendLiteral(":")
    .appendMinuteOfHour(2)
    .appendLiteral(":")
    .appendSecondOfMinute(2)
    .toFormatter()

  return toDateTime(DateTimeZone.forID("Asia/Tokyo")).toString(formatter)
}

fun Instant.isExpired() = isBeforeNow

/**
 * Convert UTC timezone to Japan timezone
 */
fun Instant.toJapanDateTime(): DateTime = this.toDateTime().withZone(DateTimeZone.forID("Japan"))

fun Int.toJpDayString(): String = when (this) {
  1 -> Constant.JPDate.Mon.toString()
  2 -> Constant.JPDate.Tue.toString()
  3 -> Constant.JPDate.Wed.toString()
  4 -> Constant.JPDate.Thu.toString()
  5 -> Constant.JPDate.Fri.toString()
  6 -> Constant.JPDate.Sat.toString()
  7 -> Constant.JPDate.Sun.toString()
  else -> throw InvalidParameterException("Invalid day")
}

fun Int.toTimeString(): String = when (this) {
  in 0..9 -> "0$this"
  else -> "$this"
}